package cn.edu.hnu.gpg.service;

import cn.edu.hnu.gpg.dao.StudentMapper;
import cn.edu.hnu.gpg.dto.Account;
import cn.edu.hnu.gpg.dto.AccountSearchTerm;
import cn.edu.hnu.gpg.entity.*;
import cn.edu.hnu.gpg.entity.enums.Gender;
import cn.edu.hnu.gpg.entity.enums.UserType;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class StudentServiceImpl implements StudentService {

    static private final Logger logger = LogManager.getLogger(StudentService.class);

    @Autowired
    private UserService userService;

    private StudentMapper studentMapper;

    @Autowired
    public StudentServiceImpl(StudentMapper studentMapper){
        this.studentMapper=studentMapper;
    }

    @Override
    public Student findStudentByUserId(int user_id) {
        if(user_id<=0)
            return null;

        StudentExample studentExample = new StudentExample();
        studentExample.or().andUserIdEqualTo(user_id);
        List<Student> students  = studentMapper.selectByExample(studentExample);
        return students.size()>0 ? students.get(0) : null;
    }

    @Override
    public Student findStudentByStudentId(int student_id) {
        if (student_id < 1)
            return null;

        return studentMapper.selectByPrimaryKey(student_id);
    }

    @Override
    public List<Student> findStudentLike(Student student) {

        StudentExample example = new StudentExample();

        if (student.getStudentNumber() != null && !student.getStudentNumber().isEmpty())
            example.or().andStudentNumberLike(student.getStudentNumber() + "%");
        if (student.getIdNumber() != null && !student.getIdNumber().isEmpty())
            example.or().andIdNumberLike(student.getIdNumber() + "%");
        if (student.getName() != null && !student.getName().isEmpty())
            example.or().andNameLike(student.getName() + "%");

        return studentMapper.selectByExample(example);
    }

    @Override
    public List<Account> findStudentAccountLike(Student student, boolean onlyActiveAccount) {
        List<Account> accountList;

        try {
            List<Student> studentList = findStudentLike(student);
            accountList = new ArrayList<>(studentList.size());

            for (Student s : studentList) {
                User user = userService.findUserByUsername(s.getStudentNumber());

                if (user == null)
                    continue;

                if (onlyActiveAccount && !user.getActive()) {
                    continue;
                }

                Account account = new Account(s);
                account.setUser(user);
                accountList.add(account);
            }

            return accountList;
        } catch (Exception e) {
            logger.debug(e);
            return null;
        }
    }

    @Override
    public List<Student> findStudentByStudentId(List<Integer> studentIdList) {

        StudentExample example = new StudentExample();
        example.or().andStudentIdIn(studentIdList);

        return studentMapper.selectByExample(example);
    }

    @Override
    public int createStudent(int user_id, String student_number, String id_number, String name, Gender gender, @Nullable Date birth_date,
                             @Nullable String phone, short department_id, short enrollment_year) {
        if(user_id<=0)
            return 0;

        if(student_number.isEmpty())
            throw new IllegalArgumentException("student_number is empty");

        if(id_number.isEmpty())
            throw new IllegalArgumentException("id_number is empty");

        if (name.isEmpty())
            throw new IllegalArgumentException("name is empty");

        if(gender == null)
            throw new IllegalArgumentException("gender is null");

        if (enrollment_year <1900 || enrollment_year>2100)
            throw new IllegalArgumentException("enrollment_year is invalid");

        Student student = new Student();
        student.setUserId(user_id);
        student.setStudentNumber(student_number);
        student.setIdNumber(id_number);
        student.setName(name);
        student.setGender(gender);
        student.setBirthDate(birth_date);
        student.setPhone(phone);
        student.setDepartmentId(department_id);
        student.setEnrollmentYear(enrollment_year);

        int id = studentMapper.insertSelective(student);

        if (id == 1)
            return student.getStudentId();
        else return id;
    }

    @Override
    public int createStudentAccount(String student_number, String id_number, String name, Gender gender,@Nullable Date birth_date,
                                    @Nullable String phone, short department_id, short enrollment_year) {
        //注册用户时，使用学生的student_number,id_number分别做为用户名和密码，可确保数据的唯一性，亦方便记忆
        int user_id = userService.createUser(student_number,id_number,UserType.S);

        //创建教师
        int id = createStudent(user_id, student_number, id_number, name,gender, birth_date, phone, department_id, enrollment_year);

        return id;
    }

    @Override
    public int createStudentAccount(Student student) {

        if (student == null)
            throw new IllegalArgumentException("Argument 'student' cannot be null");

        int userId = userService.createUser(student.getStudentNumber(), student.getIdNumber().substring(12), UserType.S);
        student.setUserId(userId);
        studentMapper.insertSelective(student);

        return student.getStudentId();
    }

    @Override
    public boolean updateInfo(int user_id, String student_number, String id_number, String name, Gender gender,@Nullable Date birth_date,
                              @Nullable String phone, short department_id, short enrollment_year) {
        if(user_id<=0)
            return false;

        if(student_number.isEmpty())
            throw new IllegalArgumentException("student_number is empty");

        if(id_number.isEmpty())
            throw new IllegalArgumentException("id_number is empty");

        if (name.isEmpty())
            throw new IllegalArgumentException("name is empty");

        if(gender == null)
            throw new IllegalArgumentException("gender is null");

        if (enrollment_year <1900 || enrollment_year>2100)
            throw new IllegalArgumentException("enrollment_year is invalid");

        //通过user_id获取对应的student对象
        Student student = findStudentByUserId(user_id);

        //若有修改的数据，通过下面的操作可确保将需要修改的属性列更新
        student.setStudentNumber(student_number);
        student.setIdNumber(id_number);
        student.setName(name);
        student.setGender(gender);
        student.setBirthDate(birth_date);
        student.setPhone(phone);
        student.setDepartmentId(department_id);
        student.setEnrollmentYear(enrollment_year);

        return studentMapper.updateByPrimaryKey(student) >= 1;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateStudentByStudentNumber(Student student, boolean skipNull) {
        if (student.getStudentNumber() == null)
            throw new RuntimeException("Student number is null");

        StudentExample studentExample = new StudentExample();
        studentExample.or().andStudentNumberEqualTo(student.getStudentNumber());

        int successLines;
        if (skipNull) {
            successLines = studentMapper.updateByExampleSelective(student, studentExample);
        } else {
            successLines = studentMapper.updateByExample(student, studentExample);
        }

        return successLines >= 1;
    }
}
